home *** CD-ROM | disk | FTP | other *** search
/ Atari Mega Archive 1 / Atari Mega Archive - Volume 1.iso / mint / mint104s.zoo / mint.src / xbios.c < prev    next >
C/C++ Source or Header  |  1993-03-08  |  6KB  |  278 lines

  1. /*
  2. Copyright 1990,1991,1992 Eric R. Smith.
  3. Copyright 1992 Atari Corporation.
  4. All rights reserved.
  5. */
  6.  
  7. /*
  8.  * XBIOS replacement routines
  9.  */
  10.  
  11. #include "mint.h"
  12.  
  13. extern int tosvers;    /* from main.c */
  14.  
  15. #define XBIOS_MAX 0x80
  16.  
  17. Func xbios_tab[XBIOS_MAX];    /* initially all zeros */
  18. short xbios_max = XBIOS_MAX;
  19.  
  20. /* NOTE: has_bconmap is initialized in main.c */
  21.  
  22. int has_bconmap;    /* flag: set if running under a version
  23.              * of TOS which supports Bconmap
  24.              */
  25.  
  26. /*
  27.  * Supexec() presents a lot of problems for us: for example, the user
  28.  * may be calling the kernel, or may be changing interrupt vectors
  29.  * unexpectedly. So we play some dirty tricks here: the function
  30.  * call is treated like a signal handler, and we take advantage
  31.  * of the fact that no context switches will take place while
  32.  * in supervisor mode. ASSUMPTION: the user will not choose to
  33.  * switch back to user mode, or if s/he does it will be as part
  34.  * of a longjmp().
  35.  *
  36.  * BUG: if the user function switches to user mode, then back to
  37.  * supervisor mode and returns, then the returned value may be
  38.  * inaccurate (this happens if two programs make Supexec calls
  39.  * at the same time).
  40.  */
  41.  
  42. long ARGS_ON_STACK (*usrcall) P_((long, long,long,long,long,long));
  43. long usrret;
  44. long usrarg1, usrarg2, usrarg3, usrarg4, usrarg5;
  45.  
  46. #if 0
  47. /* moved to syscall.spp */
  48. static void ARGS_ON_STACK do_usrcall P_((void));
  49.  
  50. static void ARGS_ON_STACK
  51. do_usrcall()
  52. {
  53.     usrret = (*usrcall)((long)usrcall, usrarg1, usrarg2, usrarg3, usrarg4,
  54.          usrarg5);
  55. }
  56. #endif
  57.  
  58. long ARGS_ON_STACK
  59. supexec(funcptr, arg1, arg2, arg3, arg4, arg5)
  60.     Func funcptr;
  61.     long arg1, arg2, arg3, arg4, arg5;
  62. {
  63.     short savesr;
  64.     CONTEXT *syscall = &curproc->ctxt[SYSCALL];
  65.  
  66. /* set things up so that "signal 0" will be handled by calling the user's
  67.  * function.
  68.  */
  69.  
  70.     usrcall = funcptr;
  71.     usrarg1 = arg1;
  72.     usrarg2 = arg2;
  73.     usrarg3 = arg3;
  74.     usrarg4 = arg4;
  75.     usrarg5 = arg5;
  76.     curproc->sighandle[0] = (long)do_usrcall;
  77.     savesr = syscall->sr;    /* save old super/user mode flag */
  78.     syscall->sr |= 0x2000;    /* set supervisor mode */
  79.     handle_sig(0);        /* actually call out to the user function */
  80.     syscall->sr = savesr;
  81.  
  82. /* do_usrcall saves the user's return value in usrret */
  83.     return usrret;
  84. }
  85.  
  86.  
  87. /*
  88.  * midiws: we have to replace this, because it's possible that the process'
  89.  * view of what the MIDI port is has been changed by Fforce or Fmidipipe
  90.  */
  91.  
  92. long ARGS_ON_STACK
  93. midiws(cnt, buf)
  94.     int cnt;
  95.     const char *buf;
  96. {
  97.     FILEPTR *f;
  98.     long towrite = cnt+1;
  99.  
  100.     f = curproc->handle[-5];    /* MIDI output handle */
  101.     if (!f) return EIHNDL;
  102.  
  103.     if (is_terminal(f)) {
  104.         while (cnt >= 0) {
  105.             tty_putchar(f, (long)*buf, RAW);
  106.             buf++; cnt--;
  107.         }
  108.         return towrite;
  109.     }
  110.     return (*f->dev->write)(f, buf, towrite);
  111. }
  112.  
  113. /*
  114.  * Modem control things: these are replaced because we handle
  115.  * Bconmap ourselves
  116.  */
  117.  
  118. /* mapin: utility routine, does a Bconmap and keeps track
  119.  * so we call the kernel only when necessary; call this
  120.  * only if has_bconmap is "true".
  121.  * Returns: 0 on failure, 1 on success.
  122.  */
  123. int curbconmap;
  124.  
  125. int
  126. mapin(dev)
  127.     int dev;
  128. {
  129.     long r;
  130.  
  131.     if (dev == curbconmap)
  132.         return 1;
  133.     r = Bconmap(dev);
  134.     if (r) {
  135.         curbconmap = dev;
  136.         return 1;
  137.     }
  138.     return 0;
  139. }
  140.     
  141. long ARGS_ON_STACK
  142. uiorec(dev)
  143.     int dev;
  144. {
  145.     TRACE(("Iorec(%d)", dev));
  146.     if (dev == 0 && has_bconmap)
  147.         mapin(curproc->bconmap);
  148.     return (long)Iorec(dev);
  149. }
  150.  
  151. long ARGS_ON_STACK
  152. rsconf(baud, flow, uc, rs, ts, sc)
  153.     int baud, flow, uc, rs, ts, sc;
  154. {
  155.     long rsval;
  156.     static int oldbaud = -1;
  157.     int ret_oldbaud = 0;
  158.     IOREC_T *ior;
  159.  
  160.     TRACE(("Rsconf(%d,%d,%d,%d,%d,%d)", baud, flow,
  161.         uc, rs, ts, sc));
  162.  
  163.     if (has_bconmap)
  164.         mapin(curproc->bconmap);
  165.  
  166. #ifndef DONT_ONLY030_THIS
  167. /* Note: in theory, the code below shouldn't be necessary
  168. if we're running on a 68030 chip; after all, in such a case
  169. we MUST have TOS 1.6 or better...
  170. However, the code breaks if we comment this out, even though
  171. tosvers is indeed > 0x0104. Must be a compiler bug, but it's
  172. nothing obvious!
  173. */
  174.  
  175. /*
  176.   If this is an old TOS, try to rearrange things to support
  177.   the following Rsconf() features:
  178.     1. Rsconf(-2, ...) does not return current baud (it crashes)
  179.         -> keep track of old speed in static variable
  180.     2. Rsconf(b, ...) sends ASCII DEL to the modem unless b == -1
  181.         -> make speed parameter -1 if new speed matches old speed
  182.     3. Rsconf() discards any buffered output
  183.         -> use Iorec() to ensure all buffered data was sent before call
  184. */
  185.     else if (tosvers < 0x0104) {
  186.         if (baud == -2) {
  187.             ret_oldbaud = 1;
  188.             baud = -1;
  189.         } else if (baud == oldbaud)
  190.             baud = -1;
  191.         else if (baud > -1)
  192.             oldbaud = baud;
  193.     }
  194. /* This part _is_ necessary on TOS 1.04 */
  195.     if (tosvers <= 0x0104) {
  196.         int attempts = 0;
  197.         short old_head;
  198.         ior = ((IOREC_T *) uiorec(0)) + 1; /* output record */
  199.         old_head = ior->head;
  200.         while (ior->head != ior->tail) {
  201.             if (++attempts >= 50) { /* prevent getting stuck by flow control */
  202.                 if (old_head == ior->head)
  203.                     break;
  204.                 else {
  205.                     old_head = ior->head;
  206.                     attempts = 0;
  207.                 }
  208.             }
  209.             TRACE(("Rsconf() napping until transmit buf empty"));
  210.             nap(200);
  211.         }
  212.     }
  213. #endif /* ONLY030 */
  214.  
  215.     rsval = Rsconf(baud, flow, uc, rs, ts, sc);
  216.     if (ret_oldbaud)
  217.         rsval = (long) oldbaud;
  218.  
  219.     return rsval;
  220. }
  221.  
  222. long ARGS_ON_STACK
  223. bconmap(dev)
  224.     int dev;
  225. {
  226.     int old = curproc->bconmap;
  227.  
  228.     TRACE(("Bconmap(%d)", dev));
  229.  
  230.     if (has_bconmap) {
  231.         if (dev == -1) return old;
  232.         if (dev == -2) return Bconmap(-2);
  233.         if (dev == 0) return 0;  /* the user's just testing */
  234.         if (mapin(dev) == 0) {
  235.             DEBUG(("Bconmap: mapin(%d) failed", dev));
  236.             return 0;
  237.         }
  238.         if (set_auxhandle(curproc, dev) == 0) {
  239.             DEBUG(("Bconmap: Couldn't change AUX:"));
  240.             return 0;
  241.         }
  242.         curproc->bconmap = dev;
  243.         return old;
  244.     }
  245.     return EINVFN;    /* no Bconmap available */
  246. }
  247.  
  248. /*
  249.  * cursconf(): this gets converted into an ioctl() call on
  250.  * the appropriate device
  251.  */
  252.  
  253. long ARGS_ON_STACK
  254. cursconf(cmd, op)
  255.     int cmd, op;
  256. {
  257.     FILEPTR *f;
  258.  
  259.     f = curproc->handle[-1];
  260.     if (!f || !is_terminal(f))
  261.         return EINVFN;
  262.     return
  263.       (*f->dev->ioctl)(f, TCURSOFF+cmd, &op);
  264. }
  265.  
  266. void
  267. init_xbios()
  268. {
  269.     curbconmap = (has_bconmap) ? (int) Bconmap(-1) : 1;
  270.  
  271.     xbios_tab[0x0c] = midiws;
  272.     xbios_tab[0x0e] = uiorec;
  273.     xbios_tab[0x0f] = rsconf;
  274.     xbios_tab[0x15] = cursconf;
  275.     xbios_tab[0x26] = supexec;
  276.     xbios_tab[0x2c] = bconmap;
  277. }
  278.